#include "Point.h"
#include <math.h>
#include "MathHelper.h"

const Point Point::ZERO = Point( 0, 0 );
const Point Point::ONE	= Point( 1, 1 );

//-----------------------------------------------------------------------------//
//-----------------------Constructors and Destructor---------------------------//
//-----------------------------------------------------------------------------//

Point::Point(void)
{
	X = 0;
	Y = 0;
}

Point::Point(int x, int y)
{
	X = x;
	Y = y;
}

Point::Point(const Point& rhs)
{
	this->X = rhs.X;
	this->Y = rhs.Y;
}

Point::~Point(void)
{
	// do nothing
}

//----------------------------------------------------//
//-------------------- Operators ---------------------//
//----------------------------------------------------//

Point& Point::operator=(const Point& rhs)
{	
    if ( this == &rhs )
	{
		return *this;
	}

	this->X = rhs.X;
	this->Y = rhs.Y;
	return *this;
}

Point Point::operator +(const Point& rhs) const
{
	return Point( X + rhs.X, Y + rhs.Y ); 
}

Point Point::operator -(const Point& rhs) const
{
	return Point( X - rhs.X, Y - rhs.Y ); 
}

Point Point::operator *(const int scalar) const
{
	return Point( X * scalar, Y * scalar ); 
}

Point Point::operator /(const int scalar) const
{
	return Point( X / scalar, Y / scalar );
}

Point& Point::operator +=( const Point& rhs)
{
	X += rhs.X;
    Y += rhs.Y;

    return *this;
}

Point& Point::operator -=( const Point& rhs)
{
	X -= rhs.X;
    Y -= rhs.Y;

    return *this;
}

Point& Point::operator *=( const int scalar)
{
	X *= scalar;
    Y *= scalar;

    return *this;
}

Point& Point::operator /=( const int scalar)
{
	X /= scalar;
    Y /= scalar;

    return *this;
}

bool Point::operator ==(const Point &rhs)
{
	return ( X == rhs.X && Y == rhs.Y );
}

bool Point::operator !=(const Point& rhs)
{
	return !( *this == rhs );
}

Point Point::operator -() const
{
	return Point( -X, -Y );
}

//-----------------------------------------------------------------------------//
//----------------------------Member Functions---------------------------------//
//-----------------------------------------------------------------------------//


Point Point::Add(const Point &rhs)
{
	return Point( X + rhs.X, Y + rhs.Y );
}

Point Point::Subtract(const Point &rhs)
{
	return Point( X - rhs.X, Y - rhs.Y );
}

Point Point::Multiply(int scalar)
{
	return Point( X * scalar, Y * scalar );
}

Point Point::Divide(int scalar)
{
	return Point( X / scalar, Y / scalar );
}

float Point::Length() const
{
	return sqrtf( static_cast<float>( ( X * X ) + ( Y * Y ) ) );
}

float Point::LengthSquared() const
{
	return static_cast<float>( ( X * X ) + ( Y * Y ) );
}

inline bool Point::Equals(const Point &v) const
{
	return ( X == v.X && Y == v.Y );
}

//-----------------------------------------------------------------------------//
//----------------------------Static Functions---------------------------------//
//-----------------------------------------------------------------------------//

float Point::Distance(const Point &lhs, const Point &rhs)
{
	Point temp = lhs - rhs;
	return temp.Length();
}

float Point::DistanceSquared(const Point &lhs, const Point &rhs)
{
	return static_cast<float>( ( lhs.X * rhs.X ) + ( lhs.Y * rhs.Y ) );
}

Point Point::Lerp(const Point &start, const Point &end, int amount)
{
	int theta = ( start.X * end.X + start.Y * end.Y );
	Point r = end * amount;

	if ( theta >= MathHelper::ToRadian( 90 ) )
	{
		r += ( start * ( 1 - amount ) );
	}
	else
	{
		r += ( start * ( amount - 1 ) );
	}

	return r;
}

